/**
 * eventEmitter
 *
 * @file 发布订阅模式
 * */

/**
 * EventEmitter - 发布订阅模式基类
 *
 * @class
 * @extends Object
 * */
export const EventEmitter = function () {
    return {
        /**
         * events - 注册表对象
         *
         * @type Object
         * @memberOf EventEmitter
         * */
        events: {},
        /**
         * on - 发布
         *
         * @function
         * @param { String } eventName - 注册事件名
         * @param { Function } callback - 注册事件锚定处理方法
         * @memberOf EventEmitter
         * */
        on: function (eventName, callback) {
            if (this.events[eventName]) {
                //如果有就放一个新的
                this.events[eventName].push(callback);
            } else {
                //如果没有就创建一个数组
                this.events[eventName] = [callback];
            }
        },
        /**
         * emit - 订阅
         *
         * @function
         * @param { String } eventName - 订阅事件名
         * @param { any } rest - 订阅事件传参
         * @memberOf EventEmitter
         * */
        emit: function (eventName, ...rest) {
            if (this.events[eventName]) {
                // 循环执行订阅方法
                this.events[eventName].forEach(item => {
                    item.apply(this, rest);
                });
            }
        },
        /**
         * removeListener - 取消对应事件监听
         *
         * @function
         * @param { String } eventName - 注册事件名
         * @param { Function } callback - 注册事件锚定处理方法
         * @memberOf EventEmitter
         * */
        removeListener: function (eventName, callback) {
            if (this.events[eventName]) {
                // 当前数组和传递过来的 callback 相等则移除掉
                this.events[eventName] = this.events[eventName].filter(item => item !== callback);
            }
        },
        /**
         * once - 单次发布
         *
         * @function
         * @param { String } eventName - 注册事件名
         * @param { any } callback - 注册事件传参
         * @memberOf EventEmitter
         * */
        once: function (eventName, callback) {
            const that = this;

            const one = function () {
                // 在 one 函数运行原来的函数，然后将 one 清空
                callback.apply(that, arguments);
                // 先绑定 执行后再删除
                that.removeListener(eventName, one);
            }
            // 此时 emit 触发会执行此函数，会给这个函数传递 rest 参数
            this.on(eventName, one);
        }
    }
}

export default EventEmitter;
